import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from scipy import stats
from sklearn.preprocessing import StandardScaler

# 设置中文字体（选择系统中已安装的中文字体）
plt.rcParams["font.family"] = ["SimHei"]
# 解决负号显示问题
plt.rcParams['axes.unicode_minus'] = False  # 正确显示负号

# 使用箱线图方法识别异常值
def boxplot_outliers( path):
    # 加载数据
    data = pd.read_csv(path)
    # 设置图片清晰度
    plt.rcParams['figure.dpi'] = 300
    # 设置中文字体
    plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei']
    # 绘制箱线图
    data[['Age', 'MonthlyIncome']].plot.box()
    plt.title('识别异常值')
    plt.ylabel('数值')
    plt.show()
    plt.savefig('../data/fig/箱线图识别异常值.png')

# 通过箱线图方法计算获取异常值
def identify_outliers_boxplot(data, column):
    """
    使用箱线图方法识别异常值
    :param data: 数据集
    :param column: 特征列
    :return: 异常值
    """
    #通过计算下四分位数
    q1 = data[column].quantile(0.25)
    #通过计算上四分位数
    q3 = data[column].quantile(0.75)
    #计算IQR
    iqr = q3 - q1
    #计算下限和上限
    lower_bound = q1 - 1.5 * iqr
    upper_bound = q3 + 1.5 * iqr
    #低于下限或者高于上限的返回异常值
    outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)][column]
    return outliers

# 使用 z - score 方法识别异常值
def identify_outliers_zscore(data, column):
    z_scores = stats.zscore(data[column])
    outliers = data[(abs(z_scores) > 3)][column]
    return outliers


def data_preprocessing(path):
    '''
    格式化时间
    :param path: 传入需要格式的文件路径
    :return: 返回处理后的数据
    '''
    df = pd.read_csv(path)
    #删除空白值
    df.dropna(inplace=True)
    #删除无用的列
    df.drop(['Over18','EmployeeNumber'],axis=1,inplace=True)
    #对数据进行热编码处理
    encode_data = pd.get_dummies(df)
    #删除重复的列
    df.drop_duplicates(inplace=True)
    # #返回处理后的数据
    # print(df.head(5))
    return encode_data

if __name__ == '__main__':
    boxplot_outliers('../data/train.csv')

    # 数据的获取
    data = data_preprocessing('../data/train.csv')

    # 通过箱线图方法识别异常值
    # 识别 Age 特征的异常值
    age_outliers = identify_outliers_boxplot(data, 'Age')
    print('Age 特征的异常值：')
    print(age_outliers)

    # 识别 MonthlyIncome 特征的异常值
    income_outliers = identify_outliers_boxplot(data, 'MonthlyIncome')
    print('MonthlyIncome 特征的异常值：')
    print(income_outliers)
    # 结论
    # 通过箱线图的划分得出结果
    # 部分的月收入数据处于偏高的异常
    # 但是月收入数据属于有价值性的数据
    # 因此，我们再次选择使用z-score方法进行异常值识别

    #通过z-score分数去对异常值进行分析
    # 识别 Age 特征的异常值
    age_outliers_zscore = identify_outliers_zscore(data, 'Age')
    print('Age 特征基于 z - score 方法的异常值：')
    print(age_outliers_zscore)

    # 识别 MonthlyIncome 特征的异常值
    income_outliers_zscore = identify_outliers_zscore(data, 'MonthlyIncome')
    print('MonthlyIncome 特征基于 z - score 方法的异常值：')
    print(income_outliers_zscore)
    # 结论
    # 通过z-score方法得出结果
    # 没用明显的异常值





